// This software code is made available "AS IS" without warranties of any        
// kind.  You may copy, display, modify and redistribute the software            
// code either by itself or as incorporated into your code; provided that        
// you do not remove any proprietary notices.  Your use of this software         
// code is at your own risk and you waive any claim against Amazon               
// Digital Services, Inc. or its affiliates with respect to your use of          
// this software code. (c) 2006 Amazon Digital Services, Inc. or its             
// affiliates.          



using AmazonWebServices;
using System;
using System.Collections;
using System.Security.Cryptography;
using System.Text;
using com.amazon.s3;

namespace S3Sample
{
    class S3Driver
    {
        private static readonly string awsAccessKeyId = "0FX2XW6HQPF4C5HF1QR2";
        private static readonly string awsSecretAccessKey = "KhxnRAJweLUR7enbt05I1J1poTUkGh+XFjPsjqqR";

        private static readonly string bucketName = "benfulton.net";
        private static readonly string keyName = "example.txt";
        private static readonly string innerKeyName = "test/inner.txt";

        static int Main(string[] args)
        {
            try
            {
                if (awsAccessKeyId.StartsWith("<INSERT"))
                {
                    System.Console.WriteLine("Please examine S3Driver.cs and update it with your credentials");
                    return 1;
                }

                AWSAuthConnection conn = new AWSAuthConnection(awsAccessKeyId, awsSecretAccessKey);

                System.Console.WriteLine("----- creating bucket -----");
                System.Console.WriteLine(
                                         conn.createBucket( bucketName, null )
                                        );

                System.Console.WriteLine("----- listing bucket -----");
                dumpBucketListing(conn.listBucket( bucketName, null, null, 0));

                System.Console.WriteLine("----- putting object -----");
                string obj = "This is a test";
                System.Console.WriteLine(conn.put(bucketName, keyName, obj, null, null).ETag);

                System.Console.WriteLine("----- getting object -----");
                System.Console.WriteLine(conn.get(bucketName, keyName).Data);

                System.Console.WriteLine("----- listing bucket -----");
                dumpBucketListing(conn.listBucket(bucketName, null, null, 0));

                System.Console.WriteLine("----- getting the access control policy -----");
                AccessControlPolicy policy = conn.getACL(bucketName, keyName);

                System.Console.WriteLine("----- putting object with metadata and public read acl -----");
                MetadataEntry [] metadata = new MetadataEntry[1];
                metadata[0] = new MetadataEntry();
                metadata[0].Name = "blah";
                metadata[0].Value = "foo";
                obj = "this is a publicly readable test";

                // Copy the grants from before, and add the anonymous group grant.
                Grant[] grants = new Grant[ policy.AccessControlList.Length + 1 ];
                int i = 0;
                foreach ( Grant g in policy.AccessControlList ) {
                    grants[i] = g;
                    ++ i;
                }
                Group groupGrant = new Group();
                groupGrant.URI = "http://acs.amazonaws.com/groups/global/AllUsers";
                grants[i] = new Grant();
                grants[i].Grantee = groupGrant;
                grants[i].Permission = Permission.READ;

                System.Console.WriteLine(conn.put(bucketName, keyName + "-public", obj, metadata, grants).ETag);

                System.Console.WriteLine("----- anonymous read test -----");
                System.Console.WriteLine("\nYou should be able to try this in your browser\n");
                string publicURL = "http://s3.amazonaws.com/" + bucketName + "/" + keyName + "-public";
                System.Console.WriteLine(publicURL);
                System.Console.WriteLine("\npress enter >");
                System.Console.ReadLine();

                System.Console.WriteLine("----- getting object's acl -----");
                dumpAccessControlList(conn.getACL(bucketName, keyName));

                System.Console.WriteLine("----- creating another object using a delimiter for list -----");
                conn.put(bucketName, innerKeyName, obj, null, null);
                System.Console.WriteLine("----- using the delimiter in list -----");
                dumpBucketListing(conn.listBucket(bucketName, null, null, 0, "/"));
                System.Console.WriteLine("----- listing the test/ common prefix -----");
                dumpBucketListing(conn.listBucket(bucketName, "test/", null, 0, "/"));

                System.Console.WriteLine("----- deleting objects -----");
                System.Console.WriteLine(conn.delete(bucketName, keyName).Description);
                System.Console.WriteLine(conn.delete(bucketName, keyName + "-public").Description);
                System.Console.WriteLine(conn.delete(bucketName, innerKeyName).Description);

                System.Console.WriteLine("----- listing bucket -----");
                dumpBucketListing(conn.listBucket(bucketName, null, null, 0));

                System.Console.WriteLine("----- listing all my buckets -----");
                dumpAllMyBucketListing(conn.listAllMyBuckets());

                System.Console.WriteLine("----- deleting bucket -----");
                System.Console.WriteLine(conn.deleteBucket(bucketName));
                return 0;
            }
            catch (Exception ex)
            {
                System.Console.WriteLine(ex.Message);
                System.Console.WriteLine(ex.StackTrace);
                System.Console.ReadLine();
                return 1;
            }
        }

        private static void dumpBucketListing(ListBucketResult list)
        {
            if (list.CommonPrefixes != null)
            {
                foreach (PrefixEntry prefix in list.CommonPrefixes)
                {
                    System.Console.WriteLine("Prefix: " + prefix.Prefix);
                }
                System.Console.WriteLine();
            }
            if (list.Contents == null)
            {
                return;
            }
            foreach (ListEntry entry in list.Contents)
            {
                CanonicalUser o = entry.Owner;
                if (o == null)
                {
                    o = new CanonicalUser();
                    o.ID = "";
                    o.DisplayName = "";
                }
                System.Console.WriteLine( entry.Key.PadRight( 20 ) + 
                                          entry.ETag.PadRight( 20 ) +
                                          entry.LastModified.ToString().PadRight( 20 ) +
                                          o.ID.PadRight( 10 ) +
                                          o.DisplayName.PadRight( 20 ) +
                                          entry.Size.ToString().PadRight( 11 ) +
                                          entry.StorageClass.ToString().PadRight( 10 ) );
            }
        }

        private static void dumpAllMyBucketListing(ListAllMyBucketsResult list)
        {
            foreach (ListAllMyBucketsEntry entry in list.Buckets)
            {
                System.Console.WriteLine( entry.Name.PadRight(20) +
                                          entry.CreationDate.ToString().PadRight(20) );
            }
        }

        private static void dumpAccessControlList(AccessControlPolicy acl)
        {
            foreach (Grant g in acl.AccessControlList)
            {
                System.Console.WriteLine(g.Grantee.ToString() + "\t" + g.Permission);
            }
        }
    }
}
